package org.infodavid.common.model.impl;

import org.infodavid.common.model.IPerson;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

/**
 * The Class PersonImpl.
 */
public class PersonImpl extends AbstractEntity implements IPerson {

	/** serialVersionUID. */
	private static final long serialVersionUID = -9034731357151519865L;

	/** The birth date. */
	private DateTime birthDate;

	/** The death date. */
	private DateTime deathDate;

	/** The firstname. */
	private String firstName;

	/** The nationality. */
	private String nationality;

	/** The title. */
	private IPerson.EPersonTitle title;

	/**
	 * The Constructor.
	 * @param key the key
	 * @throws Exception the exception
	 */
	protected PersonImpl(final Long key) throws Exception {
		super(key);
	}

	/**
	 * The Constructor.
	 * @throws Exception the exception
	 */
	protected PersonImpl() throws Exception {
		super();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.impl.AbstractEntity#init()
	 */
	@Override
	public void init() throws Exception {
		super.init();

		birthDate = null;
		deathDate = null;
		firstName = null;
		nationality = null;
		title = null;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#getAge()
	 */
	public byte getAge() {
		final DateTime date = getBirthDate();
		byte age = 0;

		if (date != null) {
			age = (byte)(new DateTime().getYear() - date.getYear());
		}

		return age;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#getBirthDate()
	 */
	public DateTime getBirthDate() {
		return birthDate;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#getDeathDate()
	 */
	public DateTime getDeathDate() {
		return deathDate;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#getFirstName()
	 */
	public String getFirstName() {
		return firstName;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#getNationality()
	 */
	public String getNationality() {
		return nationality;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#getTitle()
	 */
	public EPersonTitle getTitle() {
		return title;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#setBirthDate(org.joda.time.DateTime)
	 */
	public void setBirthDate(final DateTime value) {
		if (!equals(birthDate, value)) {
			final Object old = birthDate;
			birthDate = value;
			markModified(BIRTH_DATE, old, birthDate);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#setDeathDate(org.joda.time.DateTime)
	 */
	public void setDeathDate(final DateTime value) {
		if (!equals(deathDate, value)) {
			final Object old = deathDate;
			deathDate = value;
			markModified(DEATH_DATE, old, deathDate);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#setFirstName(java.lang.String)
	 */
	public void setFirstName(final String value) {
		if (!equals(firstName, value)) {
			final Object old = firstName;
			firstName = value;
			markModified(FIRST_NAME, old, firstName);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#setNationality(java.lang.String)
	 */
	public void setNationality(final String value) {
		if (!equals(nationality, value)) {
			final Object old = nationality;
			nationality = value;
			markModified(NATIONALITY, old, nationality);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.entities.IPerson#setTitle(org.infodavid.common.model
	 * .entities.IPerson.EPersonTitle)
	 */
	public void setTitle(final EPersonTitle value) {
		if (!equals(title, value)) {
			final Object old = title;
			title = value;
			markModified(TITLE, old, title);
		}
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		final StringBuilder builder = new StringBuilder();

		builder.append(super.toString());
		builder.append(" [birthDate=");
		builder.append(birthDate);
		builder.append(", deathDate=");
		builder.append(deathDate);
		builder.append(", firstname=");
		builder.append(firstName);
		builder.append(", nationality=");
		builder.append(nationality);
		builder.append(", title=");
		builder.append(title);
		builder.append("]");

		return builder.toString();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.impl.DataObjectImpl#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;

		if (getBirthDate() == null) {
			result = prime * result;
		}
		else {
			result = prime * result + getBirthDate().toDateTime(DateTimeZone.UTC).hashCode();
		}

		result = prime * result + (getFirstName() == null ? 0 : getFirstName().hashCode());
		result = prime * result + (getName() == null ? 0 : getName().hashCode());

		return prime * result + (getIdentity() == null ? 0 : getIdentity().hashCode());
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.model.impl.DataObjectImpl#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}

		if (obj == null) {
			return false;
		}

		if (!(obj instanceof IPerson)) {
			return false;
		}

		final IPerson other = (IPerson)obj;

		if (getBirthDate() == null) {
			if (other.getBirthDate() != null) {
				return false;
			}
		}
		else if (!getBirthDate().equals(other.getBirthDate())) {
			return false;
		}

		if (getFirstName() == null) {
			if (other.getFirstName() != null) {
				return false;
			}
		}
		else if (!getFirstName().equals(other.getFirstName())) {
			return false;
		}

		if (getName() == null) {
			if (other.getName() != null) {
				return false;
			}
		}
		else if (!getName().equals(other.getName())) {
			return false;
		}

		if (getIdentity() == null) {
			if (other.getIdentity() != null) {
				return false;
			}
		}
		else if (!getIdentity().equals(other.getIdentity())) {
			return false;
		}
		return true;
	}
}
